/*
 * @(#)PointSpinner.java 4/8/2007
 *
 * Copyright 2002 - 2007 JIDE Software Inc. All rights reserved.
 */

package com.element.ui.spinner;

import javax.swing.*;
import javax.swing.text.DefaultFormatterFactory;
import java.awt.*;

/**
 * <code>PointSpinner</code> is a spinner that is specialized in displaying x and y value of a point.
 * <p/>
 *
 * @author Nako Ruru
 */
public class PointSpinner extends JSpinner {

	/**
	 * Constructs a complete spinner with pair of next/previous buttons and an editor for the
	 * <code>SpinnerModel</code>.
	 *
	 * @param model
	 */
	public PointSpinner(SpinnerPointModel model) {
		super(model);
		customizeSpinner();
	}


	/**
	 * Constructs a spinner with an <code>Integer SpinnerNumberModel</code> with initial value 0 and no minimum or
	 * maximum limits.
	 */
	public PointSpinner() {
		this(new SpinnerPointModel());
	}

	@Override
	protected JComponent createEditor(SpinnerModel model) {
		return new PointEditor(this);
	}

	/**
	 *
	 */
	public static class PointEditor extends DefaultEditor {

		/**
		 * @param spinner
		 */
		public PointEditor(JSpinner spinner) {
			super(spinner);
			if (!(spinner.getModel() instanceof final SpinnerPointModel model)) {
				throw new IllegalArgumentException(
						"model not a SpinnerPointModel");
			}

			JFormattedTextField.AbstractFormatter formatter = PointFormatter.getInstance();
			DefaultFormatterFactory factory = new DefaultFormatterFactory(formatter);
			final JFormattedTextField ftf = getTextField();
			ftf.setEditable(true);
			ftf.setFormatterFactory(factory);
			ftf.setHorizontalAlignment(JTextField.RIGHT);

			/* TBD - initializing the column width of the text field
			 * is imprecise and doing it here is tricky because
			 * the developer may configure the formatter later.
			 */
			String min = Integer.toString(Integer.MIN_VALUE);
			ftf.setColumns(4 + 2 * min.length());

			ftf.addPropertyChangeListener("value", evt -> {
				String text = ftf.getText();
				int comma = text.indexOf(',');
				String digit;
				int number;
				if (model.getField() == SpinnerPointModel.FIELD_X) {
					digit = text.substring(text.indexOf('(') + 1, comma).trim();
					number = text.indexOf(digit);
				} else {
					digit = text.substring(comma + 1, text.indexOf(')')).trim();
					number = text.lastIndexOf(digit);
				}
				ftf.select(number, number + digit.length());
			});
		}
	}

	private void updateField() {
		JComponent editor = getEditor();
		if (editor instanceof PointEditor && getModel() instanceof SpinnerPointModel model) {
			JFormattedTextField ftf = ((PointEditor) editor).getTextField();
			int comma = ftf.getText().indexOf(',');
			int caret = ftf.getCaretPosition();
			model.setField(caret <= comma ? SpinnerPointModel.FIELD_X : SpinnerPointModel.FIELD_Y);
		}
	}

	@Override
	public Point getNextValue() {
		updateField();
		return (Point) super.getNextValue();
	}

	@Override
	public Point getPreviousValue() {
		updateField();
		return (Point) super.getPreviousValue();
	}

	@Override
	public Point getValue() {
		return (Point) super.getValue();
	}

	protected void customizeSpinner() {
		SpinnerWheelSupport.installMouseWheelSupport(this);
	}
}
